#include "gitdaemon.h"
#include <QtCore/QString>
#include <QtCore/QFile>
#include <QtCore/QCoreApplication>

#define DEFAULT_PORT 9418

//--------------------------------------------------------------------------------------------------

GitDaemon::GitDaemon(QObject * parent)
    : QObject(parent)
{
    m_port = DEFAULT_PORT;
    m_pid = 0;
    m_exportAll = true;
    m_useDefaultPort = true;

    // Recherche d'un git-daemon démarré
    m_searchPid();
}

//--------------------------------------------------------------------------------------------------

void GitDaemon::setPort(int port)
{
    m_port = port;
}

//--------------------------------------------------------------------------------------------------

void GitDaemon::setExportAll(bool exportall)
{
    m_exportAll = exportall;
}

//--------------------------------------------------------------------------------------------------

void GitDaemon::setUseDefaultPort(bool state)
{
    m_useDefaultPort = state;
}

//--------------------------------------------------------------------------------------------------

void GitDaemon::setExecutable(const QString & exe)
{
    m_executable = exe;
}

//--------------------------------------------------------------------------------------------------

void GitDaemon::setBasePath(const QString & path)
{
    m_basepath = path;
}

//--------------------------------------------------------------------------------------------------

bool GitDaemon::hasError() const
{
    return (m_error != QProcess::UnknownError);
}

//--------------------------------------------------------------------------------------------------

bool GitDaemon::isRunning() const
{
    return m_pid > 0;
}

//--------------------------------------------------------------------------------------------------

QString GitDaemon::errorString() const
{
    switch(m_error) {
    case QProcess::FailedToStart: return QObject::tr("The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.");
    case QProcess::Crashed: return QObject::tr("The process crashed some time after starting successfully.");
    case QProcess::Timedout: return QObject::tr("The last waitFor...() function timed out. The state of QProcess is unchanged, and you can try calling waitFor...() again.");
    case QProcess::WriteError: return QObject::tr("An error occurred when attempting to write to the process.");
    case QProcess::ReadError: return QObject::tr("An error occurred when attempting to read from the process.");
    case QProcess::UnknownError:
    default: return "";
    }
}


//--------------------------------------------------------------------------------------------------

void GitDaemon::m_execute(const QString & cmd)
{
    QProcess p;
    p.setWorkingDirectory(QCoreApplication::applicationDirPath());
    p.start(cmd);
    p.waitForFinished();
    m_error = p.error();
}

//--------------------------------------------------------------------------------------------------

bool GitDaemon::start()
{
    if (isRunning())
        return true;

    QString cmd = QString("%1 daemon --base-path=%2 --detach").arg(m_executable).arg(m_basepath);

    if (m_exportAll)
        cmd += " --export-all";

    if (!m_useDefaultPort)
        cmd += QString(" --port=%1 --reuseaddr").arg(m_port);

    m_execute(cmd);
    m_searchPid();

    // Erreur lors du lancement ?
    if (!hasError()) {
        if (isRunning()) {
            emit started();
            emit message(tr("Git Daemon started"));
        } else {
            emit error(tr("Unable to start git-daemon"));
        }
    } else {
        emit error(errorString());
    }

    return !hasError();
}

//--------------------------------------------------------------------------------------------------

bool GitDaemon::stop()
{
    if (!isRunning())
        return true;

    m_execute(QString("kill %1").arg(m_pid));

    if (!hasError()) {
        m_pid = 0;
        emit stopped();
        emit message(tr("Git Daemon stopped"));
    } else {
        emit error(errorString());
    }

    return !hasError();
}

//--------------------------------------------------------------------------------------------------

void GitDaemon::m_searchPid()
{
    QProcess p;
    p.start("sh", QStringList() << "-c" << "ps ux | grep git-daemon | tr -s ' '");
    p.waitForFinished();

    // On recherche le démon git qui a le bon port
    int port = m_useDefaultPort ? DEFAULT_PORT : m_port;

    m_pid = 0;
    foreach(const QString & process, p.readAllStandardOutput().split('\n'))
    {
        const QStringList fields = process.split(' ');

        if (fields.value(10) == "git-daemon")
        {
            m_pid = fields.value(1).toInt();

            // Parcours des infos du processus à la recherche du port
            if (!m_useDefaultPort) {
                QRegExp reg(QString(".+--port=%1.+").arg(port));
                if (reg.indexIn(process) > -1)
                    return;
                m_pid = 0;
            }
        }
    }
}
